using System;
using System.Collections.Generic;
using System.Text;

namespace RapidHDL
{

    public class PipelineBufferStage : PipelineStage 
    {

        public PipelineBufferStage(Component poParentComponent, string psName, ClockComponent poClock, NodeVector pnvReset,int piWidth)
            : base(poParentComponent, psName,poClock,pnvReset,piWidth)
        {
        }

        public override void GenerateStructure()
        {
            int iWidth = InputData.Nodes.Count;
            ResetReg oRegData = new ResetReg(this, "data_reg", oClock, iWidth, true, true, false);
            ResetReg oRegDataReady = new ResetReg(this, "reg_data_ready", oClock, 1, true, true, false);
            Mux oMux = new Mux(this, "buffer_mux", iWidth, 2);

            oRegData.ResetIn.Join(nvReset);
            oRegDataReady.ResetIn.Join(nvReset);

            oRegData.ResetTo.Join(0);
            oRegDataReady.ResetTo.Join(0);

            oRegDataReady.InputNodes.Join(InputDataReady);
            OutputDataReady.Join(oRegDataReady.OutputNodes | InputDataReady);

            oRegData.InputNodes.Join(InputData);
            oMux.InputNodes[1].Join(oRegData.OutputNodes);
            oMux.InputNodes[0].Join(InputData);

            oMux.SelectNodes.Join(oRegDataReady.OutputNodes);

            oMux.OutputNodes.Join(OutputData);

            OutputEnable.Join((InputStall & !oRegDataReady.OutputNodes) | (!InputStall & oRegDataReady.OutputNodes));

            oRegDataReady.EnableNodes.Join(OutputEnable);
            oRegData.EnableNodes.Join(OutputEnable);

            OutputStall.Join(oRegDataReady.OutputNodes & InputStall);
        }
    }
}
